using System;
using Excel = Microsoft.Office.Interop.Excel;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel.Composition;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using PowersourceUIToolkit;
using UCL.Powersource.TFS;
using UCL.Powersource.Analysis;
using UCL.Powersource.Helpers;
using UCL.Powersource.ViewModels.Analysis;
using System.Windows.Controls;
using System.Collections.Specialized;
using System.IO;

namespace UCL.Powersource.ViewModels
{
    [Export(typeof(ReportingViewModel))]
    public class ReportingViewModel : ViewModelBase
    {


        PowersourceMainViewModel _PowersourceMainViewModel;
        IPowersourceExt IPowersourceExt;
        IStatisticManager IStatisticManager;
        IReportingManager IReportingManager;




        #region CurrentTfsTeamProjectCollectionConfiguration

        /// <summary>
        /// Property CurrentTfsTeamProjectCollectionConfiguration. TODODOC: Insert appropriate summary here
        /// </summary>
        public ITfsTeamProjectCollectionConfiguration CurrentTfsTeamProjectCollectionConfiguration
        {
            get
            {
                if (_PowersourceMainViewModel == null)
                    return null;
                else
                    return _PowersourceMainViewModel.CurrentTfsTeamProjectCollectionConfiguration;
            }
        }

        private void CurrentTfsTeamProjectCollectionConfiguration_RecalculateDependencies()
        {
            //Recalculate all properties here
            if (CurrentTfsTeamProjectCollectionConfiguration != null)
            {
                //To ensure we are not listening twice first we try to detach then attach
                // NOT THREAD SAFE
                CurrentTfsTeamProjectCollectionConfiguration.PropertyChanged -= CurrentTfsTeamProjectCollectionConfiguration_PropertyChanged;
                CurrentTfsTeamProjectCollectionConfiguration.PropertyChanged += CurrentTfsTeamProjectCollectionConfiguration_PropertyChanged;
            }
            AvailableReportingContextCollection_RecalculateDependencies();
            NotifyOfPropertyChange(() => CurrentTfsTeamProjectCollectionConfiguration);
        }

        private void CurrentTfsTeamProjectCollectionConfiguration_Recalculate()
        {
            CurrentTfsTeamProjectCollectionConfiguration_RecalculateDependencies();
        }

        #endregion



        #region AvailableReportingContextCollection

        /// <summary>
        /// Property AvailableReportingContextCollection. TODODOC: Insert appropriate summary here
        /// </summary>
        public ObservableCollection<ReportingContext> AvailableReportingContextCollection
        {
            get
            {
                if (CurrentTfsTeamProjectCollectionConfiguration == null) return null;
                return CurrentTfsTeamProjectCollectionConfiguration.AllReportingContextCollection;
            }
        }

        private void AvailableReportingContextCollection_RecalculateDependencies()
        {
            if (AvailableReportingContextCollection != null)
            {
                foreach (var rc in AvailableReportingContextCollection)
                {
                    rc.SynchronizeTeamsAndTimeFrames();
                    rc.SynchronizeStatistics();
                }
            }

            //if CurrentReportingContext==null we try to find first from available and use it
            if (CurrentReportingContext == null)
            {
                if (AvailableReportingContextCollection != null)
                {
                    CurrentReportingContext = AvailableReportingContextCollection.FirstOrDefault();
                }
            }
            else // else we check if CurrentReportingContext is from current AvailableReportingContextCollection and change it if neccessary
            {
                if (AvailableReportingContextCollection == null) CurrentReportingContext = null;
                else
                {
                    if (!AvailableReportingContextCollection.Contains(CurrentReportingContext))
                    {
                        CurrentReportingContext = AvailableReportingContextCollection.FirstOrDefault();
                    }
                    // else //else there is nothing to do, CurrentReportingContext is from AvailableReportingContextCollection
                }
            }

            //NotifyOfPropertyChange is usually placed as last statement - first change all dependencies and then fire property change
            NotifyOfPropertyChange(() => AvailableReportingContextCollection);
        }

        private void AvailableReportingContextCollection_Recalculate()
        {
            AvailableReportingContextCollection_RecalculateDependencies();
        }
        #endregion


        #region CurrentReportingContext

        /// <summary>
        /// Property CurrentReportingContext. TODODOC: Insert appropriate summary here
        /// </summary>
        public ReportingContext CurrentReportingContext
        {
            get { if (CurrentTfsTeamProjectCollectionConfiguration == null) return null; else return CurrentTfsTeamProjectCollectionConfiguration.CurrentReportingContext; }
            set
            {
                if (CurrentTfsTeamProjectCollectionConfiguration == null) { Log.Warn("Ignoring setter {0}.CurrentReportingContext, CurrentTfsTeamProjectCollectionConfiguration is null", this.GetType().Name); return; }
                if (CurrentTfsTeamProjectCollectionConfiguration.CurrentReportingContext == value) return;
                CurrentReportingContext_RecalculateDependencies_BeforeChanges();
                CurrentTfsTeamProjectCollectionConfiguration.CurrentReportingContext = value;
                CurrentReportingContext_RecalculateDependencies();
            }
        }

        private void CurrentReportingContext_RecalculateDependencies_BeforeChanges()
        {
            if (CurrentReportingContext != null)
            {
                CurrentReportingContext.SelectableStatistics.DetachFromSelectedItemsCollection();
                CurrentReportingContext.SelectableTimeFrames.DetachFromSelectedItemsCollection();
                CurrentReportingContext.SelectableTfsTeamProjectConfigurations.DetachFromSelectedItemsCollection();

                CurrentReportingContext.PropertyChanged -= CurrentReportingContext_PropertyChanged;
                ((INotifyCollectionChanged)(CurrentReportingContext.SelectedITfsTeamProjectConfigurations)).CollectionChanged -= CurrentReportingContext_SelectedITfsTeamProjectConfigurationsChanged;
                ((INotifyCollectionChanged)(CurrentReportingContext.SelectedITimeFrames)).CollectionChanged -= CurrentReportingContext_SelectedITimeFramesChanged;
                ((INotifyCollectionChanged)(CurrentReportingContext.SelectedIStatistics)).CollectionChanged -= CurrentReportingContext_SelectedIStatisticsChanged;
            }
        }

        private void CurrentReportingContext_RecalculateDependencies()
        {
            //Hide CurrentReportingContext settings if no CurrentReporting to configure
            if (CurrentReportingContext == null)
            {
                CurrentReportingContextExpanded = false;
                CurrentReportingContextExpandable = false;
            }
            else
            {
                if (!CurrentReportingContext.IsInitialized) CurrentReportingContext.Initialize();
                CurrentReportingContext.PropertyChanged += CurrentReportingContext_PropertyChanged;
                ((INotifyCollectionChanged)(CurrentReportingContext.SelectedITfsTeamProjectConfigurations)).CollectionChanged += CurrentReportingContext_SelectedITfsTeamProjectConfigurationsChanged;
                ((INotifyCollectionChanged)(CurrentReportingContext.SelectedITimeFrames)).CollectionChanged += CurrentReportingContext_SelectedITimeFramesChanged;
                ((INotifyCollectionChanged)(CurrentReportingContext.SelectedIStatistics)).CollectionChanged += CurrentReportingContext_SelectedIStatisticsChanged;
                CurrentReportingContextExpandable = true;
                if (CurrentStatisticViewModel != null)
                {
                    SynchronizeContextAndStatisticViewModel();
                    CurrentReportingContextExpanded = true;
                }

            }

            if (CurrentStatisticViewModel != null)
            {
                SynchronizeStatisticViewModelAndStatistics();
                CheckAndFireIfNotCalculating(CurrentStatisticViewModel, DeferredChangeNotifications.OnReportingContextChanged, CurrentReportingContext);
            }
            //NotifyOfPropertyChange is usually placed as last statement - first change all dependencies and then fire property change
            NotifyOfPropertyChange(() => CurrentReportingContext);

        }

        private void CurrentReportingContext_SelectedIStatisticsChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (CurrentStatisticViewModel != null)
            {
                SynchronizeStatisticViewModelAndStatistics();
                EnsureActionAfterCalculation(CurrentStatisticViewModel, DeferredChangeNotifications.StatisticsCollectionChanged, sender, e);

            }
        }

        

        private void CurrentReportingContext_SelectedITimeFramesChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (CurrentStatisticViewModel != null)
            {
                SynchronizeStatisticViewModelAndStatistics();
                EnsureActionAfterCalculation(CurrentStatisticViewModel, DeferredChangeNotifications.TimeFramesCollectionChanged, sender, e);

            }
        }

        void CurrentReportingContext_SelectedITfsTeamProjectConfigurationsChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (CurrentStatisticViewModel != null)
            {
                SynchronizeStatisticViewModelAndStatistics();
                EnsureActionAfterCalculation(CurrentStatisticViewModel, DeferredChangeNotifications.TeamProjectConfigurationsCollectionChanged, sender, e);

            }
        }

     

        void CurrentReportingContext_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            if (CurrentStatisticViewModel != null)
            {
                if (e.PropertyName == Helpers.PropertyExtensions.GetPropertyName(() => CurrentReportingContext.ActiveTfsTeamProjectConfiguration))
                {
                    SynchronizeStatisticViewModelAndStatistics();
                    CheckAndFireIfNotCalculating(CurrentStatisticViewModel, DeferredChangeNotifications.ActiveTfsTeamProjectConfigurationChanged);

                }
                if (e.PropertyName == Helpers.PropertyExtensions.GetPropertyName(() => CurrentReportingContext.ActiveTimeFrame))
                {
                    SynchronizeStatisticViewModelAndStatistics();
                    CheckAndFireIfNotCalculating(CurrentStatisticViewModel, DeferredChangeNotifications.ActiveTimeFrameChanged);

                }
                if (e.PropertyName == Helpers.PropertyExtensions.GetPropertyName(() => CurrentReportingContext.ActiveStatistic))
                {
                    SynchronizeStatisticViewModelAndStatistics();
                    CheckAndFireIfNotCalculating(CurrentStatisticViewModel, DeferredChangeNotifications.ActiveStatisticChanged);

                }
                if (e.PropertyName == Helpers.PropertyExtensions.GetPropertyName(() => CurrentReportingContext.ShowNormalized))
                {
                    CheckAndFireIfNotCalculating(CurrentStatisticViewModel, DeferredChangeNotifications.ShowNormalizedChanged);
                }
            }
        }


        #endregion


        #region CurrentReportingContextExpanded

        /// <summary>
        /// Field storage for property CurrentReportingContextExpanded
        /// </summary>
        private bool _CurrentReportingContextExpanded = default(bool);



        /// <summary>
        /// Property CurrentReportingContextExpanded. TODODOC: Insert appropriate summary here
        /// </summary>
        public bool CurrentReportingContextExpanded
        {
            get { return _CurrentReportingContextExpanded; }
            set { if (_CurrentReportingContextExpanded == value) return; _CurrentReportingContextExpanded = value; CurrentReportingContextExpanded_RecalculateDependencies(); }
        }

        private void CurrentReportingContextExpanded_RecalculateDependencies()
        {
            //Recalculate all properties here
            CurrentReportingInfoString_Recalculate();
            //NotifyOfPropertyChange is usually placed as last statement - first change all dependencies and then fire property change
            NotifyOfPropertyChange(() => CurrentReportingContextExpanded);
        }

        //private void CurrentReportingContextExpanded_Recalculate()
        //{
        //    _CurrentReportingContextExpanded = default(bool);
        //    //Insert your code here

        //    CurrentReportingContextExpanded_RecalculateDependencies();
        //}

        #endregion


        #region CurrentReportingContextExpandable

        /// <summary>
        /// Field storage for property CurrentReportingContextExpandable
        /// </summary>
        private bool _CurrentReportingContextExpandable = default(bool);

        /// <summary>
        /// Property CurrentReportingContextExpandable. TODODOC: Insert appropriate summary here
        /// </summary>
        public bool CurrentReportingContextExpandable
        {
            get { return _CurrentReportingContextExpandable; }
            set { if (_CurrentReportingContextExpandable == value) return; _CurrentReportingContextExpandable = value; CurrentReportingContextExpandable_RecalculateDependencies(); }
        }

        private void CurrentReportingContextExpandable_RecalculateDependencies()
        {
            //Recalculate all properties here

            //NotifyOfPropertyChange is usually placed as last statement - first change all dependencies and then fire property change
            NotifyOfPropertyChange(() => CurrentReportingContextExpandable);
        }

        //private void CurrentReportingContextExpandable_Recalculate()
        //{
        //    _CurrentReportingContextExpandable = CurrentReportingContext != null;
        //    CurrentReportingContextExpandable_RecalculateDependencies();
        //}

        #endregion


        #region CurrentReportingInfoString

        /// <summary>
        /// Field storage for property CurrentReportingInfoString
        /// </summary>
        private string _CurrentReportingInfoString = default(string);

        /// <summary>
        /// Property CurrentReportingInfoString. TODODOC: Insert appropriate summary here
        /// </summary>
        public string CurrentReportingInfoString
        {
            get { return _CurrentReportingInfoString; }
            set { if (_CurrentReportingInfoString == value) return; _CurrentReportingInfoString = value; CurrentReportingInfoString_RecalculateDependencies(); }
        }

        private void CurrentReportingInfoString_RecalculateDependencies()
        {
            //Recalculate all properties here

            //NotifyOfPropertyChange is usually placed as last statement - first change all dependencies and then fire property change
            NotifyOfPropertyChange(() => CurrentReportingInfoString);
        }

        private void CurrentReportingInfoString_Recalculate()
        {
            if (CurrentReportingContextExpanded) _CurrentReportingInfoString = "Please edit the context of the shown report:";
            else
            {
                if (CurrentReportingContext == null)
                {
                    _CurrentReportingInfoString = "There is no context chosen.";
                }
                else
                {
                    _CurrentReportingInfoString = "Please expand this control to change the context of the shown report.";

                    //var teamString=string.Join(", ", CurrentReportingContext.SelectedITfsTeamProjectConfigurations.Select(a => a.UniqueName));
                    //var teamFrameString = string.Join(", ", CurrentReportingContext.SelectedITimeFrames.Select(a => a.Label));
                    //var statisticString = string.Join(", ", CurrentReportingContext.SelectedIStatistics.Select(a => a.Label));

                    //_CurrentReportingInfoString = string.Format("{0}\n\r{1}\n\r{2}", teamString, teamFrameString, statisticString);
                }

            }

            CurrentReportingInfoString_RecalculateDependencies();
        }

        #endregion


        #region CurrentStatisticViewModel

        /// <summary>
        /// Field storage for property CurrentStatisticViewModel
        /// </summary>
        private IStatisticViewModel _CurrentStatisticViewModel = default(IStatisticViewModel);

        /// <summary>
        /// Property CurrentStatisticViewModel. TODODOC: Insert appropriate summary here
        /// </summary>
        public IStatisticViewModel CurrentStatisticViewModel
        {
            get { return _CurrentStatisticViewModel; }
            set
            {
                if (_CurrentStatisticViewModel == value) return;
                CurrentStatisticViewModel_RecalculateDependencies_BeforeChanges();
                _CurrentStatisticViewModel = value;
                CurrentStatisticViewModel_RecalculateDependencies();
            }
        }

        private void CurrentStatisticViewModel_RecalculateDependencies_BeforeChanges()
        {
            if (_CurrentStatisticViewModel!=null) _CurrentStatisticViewModel.Deactivate();
        }

        private void CurrentStatisticViewModel_RecalculateDependencies()
        {

            if (_CurrentStatisticViewModel != null)
            {
                try
                {
                    CurrentStatisticViewModel.Initialize();
                    var control1 = UIManager.GetOrCreateControl(CurrentStatisticViewModel);
                    CurrentStatisticViewModel.OnReportingContextChanged(CurrentReportingContext);
                    CurrentStatisticControl = control1;
                    if (CurrentReportingContext != null)
                    {
                        CurrentReportingContextExpandable = true;
                        CurrentReportingContextExpanded = true;
                    }
                }
                catch (Exception exc)
                {
                    RaiseStatisticViewModelErrorEvent(CurrentStatisticViewModel, exc);
                }

            }
            SynchronizeContextAndStatisticViewModel();
            SynchronizeStatisticViewModelAndStatistics();
            //NotifyOfPropertyChange is usually placed as last statement - first change all dependencies and then fire property change
            NotifyOfPropertyChange(() => CurrentStatisticViewModel);
        }

        private void SynchronizeContextAndStatisticViewModel()
        {
            if (CurrentReportingContext != null && CurrentStatisticViewModel != null)
            {
                CurrentReportingContext.CurrentRegisteredStatistics = IReportingManager.GetRegisteredStatistics(CurrentStatisticViewModel);
            }
        }

        private void SynchronizeStatisticViewModelAndStatistics(bool forceRecalculate = false)
        {
            
            if (CurrentStatisticViewModel == null) return;
            if (CurrentReportingContext != null && CurrentStatisticControl != null)
            {
                var crc = CurrentReportingContext;
                var csvm = CurrentStatisticViewModel;
                SynchronizeStatisticViewModelAndStatistics(csvm, crc,forceRecalculate);
            }
        }

        private void SynchronizeStatisticViewModelAndStatistics(IStatisticViewModel csvm, ReportingContext crc, bool forceRecalculate = false)
        {
            if (csvm == null || crc == null) return;
            List<ITfsTeamProjectConfiguration> tps = new List<ITfsTeamProjectConfiguration>();
            List<ITimeFrame> tfs = new List<ITimeFrame>();
            List<IStatistic> stats = new List<IStatistic>();

            // First we get which statistcs must be recalculated

            if (csvm.IsConsumingActiveStatistic)
            {
                if (crc.ActiveStatistic != null)
                {
                    stats.Add(crc.ActiveStatistic);
                }
            }
            else
            {
                if (crc.SelectableStatistics != null && crc.SelectedIStatistics.Count > 0)
                {
                    stats.AddRange(crc.SelectableStatistics.SelectedItemsCollection);
                }
            }
            switch (csvm.StatisticViewModelType)
            {
                case StatisticViewModelTypes.SingleTeam_SingleTimeFrame:
                case StatisticViewModelTypes.SingleTeam_MultipleTimeFrames:
                    if (crc.ActiveTfsTeamProjectConfiguration == null) return;
                    tps.Add(crc.ActiveTfsTeamProjectConfiguration);
                    break;
                case StatisticViewModelTypes.MultipleTeams_SingleTimeFrame:
                case StatisticViewModelTypes.MultipleTeams_MultipleTimeFrames:
                    if (crc.SelectableTfsTeamProjectConfigurations == null || crc.SelectedITfsTeamProjectConfigurations.Count == 0) return;
                    tps.AddRange(crc.SelectableTfsTeamProjectConfigurations.SelectedItemsCollection);
                    break;
                default:
                    break;

            }
            switch (csvm.StatisticViewModelType)
            {
                case StatisticViewModelTypes.SingleTeam_SingleTimeFrame:
                case StatisticViewModelTypes.MultipleTeams_SingleTimeFrame:
                    if (crc.ActiveTimeFrame == null) return;
                    tfs.Add(crc.ActiveTimeFrame);
                    break;
                case StatisticViewModelTypes.SingleTeam_MultipleTimeFrames:
                case StatisticViewModelTypes.MultipleTeams_MultipleTimeFrames:
                    if (crc.SelectedITimeFrames == null || crc.SelectedITimeFrames.Count == 0) return;
                    tfs.AddRange(crc.SelectedITimeFrames);
                    break;
                default:
                    break;
            }

            if ((stats == null || stats.Count() == 0) && CurrentStatisticViewModel != null && CurrentStatisticViewModel.IsBuildRequired)
            {

                var r = IReportingManager.GetRegisteredStatistics(CurrentStatisticViewModel);
                var cr = CurrentReportingContext;
                if (r == null || r.All(a => !a.RequiresBuild))
                {
                    List<ITfsTeamProjectConfiguration> teams = new List<ITfsTeamProjectConfiguration>();
                    List<ITimeFrame> timeframes = new List<ITimeFrame>();
                    switch (CurrentStatisticViewModel.StatisticViewModelType)
                    {
                        case StatisticViewModelTypes.SingleTeam_SingleTimeFrame:
                            if (cr.ActiveTfsTeamProjectConfiguration != null) teams.Add(cr.ActiveTfsTeamProjectConfiguration);
                            if (cr.ActiveTimeFrame != null) timeframes.Add(cr.ActiveTimeFrame);
                            break;
                        case StatisticViewModelTypes.SingleTeam_MultipleTimeFrames:
                            if (cr.ActiveTfsTeamProjectConfiguration != null) teams.Add(cr.ActiveTfsTeamProjectConfiguration);
                            if (cr.SelectedITimeFrames != null) timeframes.AddRange(cr.SelectedITimeFrames);
                            break;
                        case StatisticViewModelTypes.MultipleTeams_SingleTimeFrame:
                            if (cr.SelectedITfsTeamProjectConfigurations != null) teams.AddRange(cr.SelectedITfsTeamProjectConfigurations);
                            if (cr.ActiveTimeFrame != null) timeframes.Add(cr.ActiveTimeFrame);
                            break;
                        case StatisticViewModelTypes.MultipleTeams_MultipleTimeFrames:
                            if (cr.SelectedITfsTeamProjectConfigurations != null) teams.AddRange(cr.SelectedITfsTeamProjectConfigurations);
                            if (cr.SelectedITimeFrames != null) timeframes.AddRange(cr.SelectedITimeFrames);
                            break;
                        default:
                            break;
                    }
                    foreach (var team in teams)
                    {
                        foreach (var tf in timeframes)
                        {
                            var innerPath = AnalysisBridge.Conventions.GetLocalPathFor(team.TeamProjectCollectionConfiguration, team, tf);
                            if (forceRecalculate)
                            {
                                if (Directory.Exists(innerPath))
                                {
                                    Directory.Delete(innerPath, true);
                                }
                            }

                            team.ProjectAnalysisBridge.RetrieveCodeIndexOrEnqueue(tf, forceRecalculate);
                        }
                    }
                }
                IsCalculating_RecalculateDependencies();
            }
            
            
            
            
            
            if (stats == null || stats.Count() == 0) return;
            if (tps == null || tps.Count() == 0) return;
            if (tfs == null || tfs.Count() == 0) return;
            EnsureStatisticsResolved(stats, tps, tfs, forceRecalculate);
        }

        IRemoteBuilderQueue _RemoteBuilderQueue;

        public IRemoteBuilderQueue RemoteBuilderQueue
        {
            get
            {
            if (_RemoteBuilderQueue== null)
                {
                    _RemoteBuilderQueue = IoC.Get<IRemoteBuilderQueue>();
                    if (_RemoteBuilderQueue!= null)
                    {

                        _RemoteBuilderQueue.RemoteBuilderQueueUpdated += _RemoteBuilderQueue_RemoteBuilderQueueUpdated;
                        _RemoteBuilderQueue.PropertyChanged += _RemoteBuilderQueue_PropertyChanged;
                    }
                }
                return _RemoteBuilderQueue;
            }
        }

        

        

        IStatisticManagerQueue _StatisticManagerQueue;
        public IStatisticManagerQueue StatisticManagerQueue
        {
            get
            {
                if (_StatisticManagerQueue == null)
                {
                    _StatisticManagerQueue = IStatisticManager.StatisticManagerQueue;
                    if (_StatisticManagerQueue != null)
                    {
                        _StatisticManagerQueue.StatisticManagerQueueUpdated += _StatisticManagerQueue_StatisticManagerQueueUpdated;
                        _StatisticManagerQueue.PropertyChanged += _StatisticManagerQueue_PropertyChanged;
                    }
                }
                return _StatisticManagerQueue;
            }
        }

        void _StatisticManagerQueue_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            //if (Helpers.PropertyExtensions.IsPropertyChanged(e, () => StatisticManagerQueue.IsCalculating))
            //{
            //    IsCalculating = StatisticManagerQueue.IsCalculating;
            //}
            //if (Helpers.PropertyExtensions.IsPropertyChanged(e, () => StatisticManagerQueue.CurrentAction))
            //{
            //    CurrentAction = StatisticManagerQueue.CurrentAction;
            //}
        }

        private IPackageConfiguration PackageConfiguration
        {
            get { return ViewModelLocator.GetViewModel<PowersourceMainViewModel>().PackageConfiguration; }
        }

        private string ConfigFileName
        {
            get { return PowersourceMainViewModel.TFSConfigFileName; }
        }


        void _RemoteBuilderQueue_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            

        }
        
        private int previousFinishedStatsCount;

        void _RemoteBuilderQueue_RemoteBuilderQueueUpdated(object sender, RemoteBuilderQueueEventArgs e)
        {
            CurrentActionMessage_RMQ = e.CurrentActionMessage;
            CurrentAction_RMQ = e.CurrentAction;
            IsCalculating_RMQ = e.IsCalculating;
            CurrentActionProgress_Max_RMQ = e.FinishedBuildsCount+ e.WaitingBuildsCount;
            CurrentActionProgress_Value_RMQ = e.FinishedBuildsCount;
            CurrentActionProgress_Max_Recalculate();
            CurrentActionProgress_Value_Recalculate();
            IsCalculating_RecalculateDependencies();
        }

        private bool IsCalculating_SMQ;
        //private string CurrentAction_SMQ;
        private int CurrentActionProgress_Max_SMQ;
        private int CurrentActionProgress_Value_SMQ;

        private bool IsCalculating_RMQ;
        //private string CurrentAction_RMQ;
        private int CurrentActionProgress_Max_RMQ;
        private int CurrentActionProgress_Value_RMQ;

        void _StatisticManagerQueue_StatisticManagerQueueUpdated(object sender, StatisticManagerQueueUpdatedEventArgs e)
        {
            CurrentAction_SMQ = e.CurrentAction;
            CurrentActionMessage_SMQ = e.CurrentActionMessage;
            IsCalculating_SMQ = e.IsCalculating;
            CurrentActionProgress_Max_SMQ = e.FinishedStatsCount + e.WaitingStatsCount;
            CurrentActionProgress_Value_SMQ = e.FinishedStatsCount;
            CurrentActionProgress_Max_Recalculate();
            CurrentActionProgress_Value_Recalculate();
            IsCalculating_RecalculateDependencies();

            if (previousFinishedStatsCount < e.FinishedStatsCount)
            {
                PackageConfigurationLoader.Save(PackageConfiguration, ConfigFileName);
                previousFinishedStatsCount = e.FinishedStatsCount;
            }
            Log.DebugMethod("CurrentAction_SMQ = {0}, CurrentAction_RMQ ={1}, IsCalculating = {2}, CurrentActionProgress_Max ={3},CurrentActionProgress_Value ={4}", CurrentAction_SMQ,CurrentAction_RMQ, IsCalculating, CurrentActionProgress_Max,CurrentActionProgress_Value );

        }

        private void EnsureStatisticsResolved(IEnumerable<IStatistic> stats, IEnumerable<ITfsTeamProjectConfiguration> projects, IEnumerable<ITimeFrame> timeframes, bool forceRecalculate)
        {
            if (_CurrentStatisticViewModel == null) return;



            string statString = "#NULL";
            var teamString = "#NULL";
            var timeframeString = "#NULL";

            IStatistic cStat = null;
            ITimeFrame cTiFr = null;
            ITfsTeamProjectConfiguration cProject = null;

            try
            {
                EnqueueingStatistics = true;
                foreach (var st in stats)
                {
                    cStat = st;
                    timeframeString = "#NULL";

                    foreach (var tif in timeframes)
                    {
                        cTiFr = tif;
                        teamString = "#NULL";
                        foreach (var pr in projects)
                        {
                            cProject = pr;
                            if (StatisticManagerQueue == null)
                            {
                                Log.Warn("Calculation will be done synchronyously as calculation queue is not available.");
                                CurrentAction_SMQ = "Calculation will be done synchronyously as calculation queue is not available.";
                                IPowersourceExt.StatisticManager.ResolveStatistic(st, pr, tif, forceRecalculate);
                            }
                            else
                            {
                                StatisticManagerQueue.EnqueueStatisticRecalculationAsync(st, pr, tif, forceRecalculate);
                            }
                        }
                    }

                }
            }
            catch (Exception exc)
            {
                Log.Error(exc, "Error while enqueueing statistics recalculation {0}, {1} ,{2}, {3}", statString, teamString, timeframeString, forceRecalculate);
                RaiseStatisticCalculationError(exc, cStat, cProject, cTiFr, forceRecalculate);
            }
            finally
            {
                EnqueueingStatistics = false;
            }
            IsCalculating_RecalculateDependencies();
            return;
        }

        public event EventHandler<StatisticCalculationErrorEventArgs> StatisticCalculationError;

        private void RaiseStatisticCalculationError(Exception exc, IStatistic cStat, ITfsTeamProjectConfiguration cProject, ITimeFrame cTiFr, bool forceRecalculate)
        {
            if (StatisticCalculationError != null)
            {
                var e = new StatisticCalculationErrorEventArgs(exc, cStat, cProject, cTiFr, forceRecalculate);
                StatisticCalculationError(this, e);
            }
        }

        bool _EnqueueingStatistics = false;
        bool EnqueueingStatistics { get { return _EnqueueingStatistics; } set { _EnqueueingStatistics = value; IsCalculating_RecalculateDependencies(); } }

        #region IsCalculating

        /// <summary>
        /// Field storage for property IsCalculating
        /// </summary>
        //private bool _IsCalculating = default(bool);

        /// <summary>
        /// Property IsCalculating. TODODOC: Insert appropriate summary here
        /// </summary>
        public bool IsCalculating
        {
            get { return _EnqueueingStatistics || IsCalculating_SMQ || IsCalculating_RMQ; }
          //  set { if (_IsCalculating == value) return; _IsCalculating = value; IsCalculating_RecalculateDependencies(); }
        }

        private void IsCalculating_RecalculateDependencies()
        {
            //Recalculate all properties here
            if (!IsCalculating)
            {
                if (CurrentStatisticViewModel != null)
                {
                    if (!CurrentStatisticViewModel.IsActivated) CurrentStatisticViewModel.Activate();
                    CurrentStatisticViewModel.Recalculate();
                    
                }
            }
            //NotifyOfPropertyChange is usually placed as last statement - first change all dependencies and then fire property change
            NotifyOfPropertyChange(() => IsCalculating);
        }

        //private void IsCalculating_Recalculate()
        //{
        //    //_IsCalculating = default(bool);

        //    IsCalculating_RecalculateDependencies();
        //}

        #endregion


        #region CurrentActionMessage_SMQ

        /// <summary>
        /// Field storage for property CurrentActionMessage
        /// </summary>
        private string _CurrentActionMessage_SMQ = default(string);

        /// <summary>
        /// Property CurrentActionMessage. TODODOC: Insert appropriate summary here
        /// </summary>
        public string CurrentActionMessage_SMQ
        {
            get { return _CurrentActionMessage_SMQ; }
            set { if (_CurrentActionMessage_SMQ == value) return; _CurrentActionMessage_SMQ = value; CurrentActionMessage_RecalculateDependencies(); }
        }

        private void CurrentActionMessage_RecalculateDependencies()
        {
            //Recalculate all properties here

            //NotifyOfPropertyChange is usually placed as last statement - first change all dependencies and then fire property change
            NotifyOfPropertyChange(() => CurrentActionMessage_SMQ);
        }

        private void CurrentActionMessage_Recalculate()
        {
            _CurrentActionMessage_SMQ = default(string);
            //Insert your code here

            CurrentActionMessage_RecalculateDependencies();
        }

        #endregion


        #region CurrentActionMessage_RMQ

        /// <summary>
        /// Field storage for property CurrentActionMessage_RMQ
        /// </summary>
        private string _CurrentActionMessage_RMQ = default(string);

        /// <summary>
        /// Property CurrentActionMessage_RMQ. TODODOC: Insert appropriate summary here
        /// </summary>
        public string CurrentActionMessage_RMQ
        {
            get { return _CurrentActionMessage_RMQ; }
            set { if (_CurrentActionMessage_RMQ == value) return; _CurrentActionMessage_RMQ = value; CurrentActionMessage_RMQ_RecalculateDependencies(); }
        }

        private void CurrentActionMessage_RMQ_RecalculateDependencies()
        {
            //Recalculate all properties here

            //NotifyOfPropertyChange is usually placed as last statement - first change all dependencies and then fire property change
            NotifyOfPropertyChange(() => CurrentActionMessage_RMQ);
        }

        private void CurrentActionMessage_RMQ_Recalculate()
        {
            _CurrentActionMessage_RMQ = default(string);
            //Insert your code here

            CurrentActionMessage_RMQ_RecalculateDependencies();
        }

        #endregion
	

        
      #region CurrentAction_SMQ
       
        /// <summary>
        /// Field storage for property CurrentAction_SMQ
        /// </summary>
        private string _CurrentAction_SMQ = default(string);

        /// <summary>
        /// Property CurrentAction_SMQ. TODODOC: Insert appropriate summary here
        /// </summary>
        public string CurrentAction_SMQ
        {
            get { return _CurrentAction_SMQ; }
            set { if (_CurrentAction_SMQ == value) return; _CurrentAction_SMQ = value; CurrentAction_SMQ_RecalculateDependencies();  }
        }

        private void CurrentAction_SMQ_RecalculateDependencies()
        {
            //Recalculate all properties here

            //NotifyOfPropertyChange is usually placed as last statement - first change all dependencies and then fire property change
            NotifyOfPropertyChange(() => CurrentAction_SMQ);
        }

        //private void CurrentAction_SMQ_Recalculate()
        //{
        //    _CurrentAction_SMQ = default(string);
        //    //Insert your code here

        //    CurrentAction_SMQ_RecalculateDependencies();
        //}

        #endregion
	
        
      #region CurrentAction_RMQ
       
        /// <summary>
        /// Field storage for property CurrentAction_RMQ
        /// </summary>
        private string _CurrentAction_RMQ = default(string);

        /// <summary>
        /// Property CurrentAction_RMQ. TODODOC: Insert appropriate summary here
        /// </summary>
        public string CurrentAction_RMQ
        {
            get { return _CurrentAction_RMQ; }
            set { if (_CurrentAction_RMQ == value) return; _CurrentAction_RMQ = value; CurrentAction_RMQ_RecalculateDependencies();  }
        }

        private void CurrentAction_RMQ_RecalculateDependencies()
        {
            //Recalculate all properties here

            //NotifyOfPropertyChange is usually placed as last statement - first change all dependencies and then fire property change
            NotifyOfPropertyChange(() => CurrentAction_RMQ);
        }

        //private void CurrentAction_RMQ_Recalculate()
        //{
        //    _CurrentAction_RMQ = default(string);
        //    //Insert your code here

        //    CurrentAction_RMQ_RecalculateDependencies();
        //}

        #endregion
	

        //private void CurrentAction_Recalculate()
        //{
        //    _CurrentAction = "Queue is empty. Computation has finished.";
        //    if (IsCalculating)
        //    {
        //        _CurrentAction = 
        //    }
        //    //Insert your code here

        //    CurrentAction_RecalculateDependencies();
        //}

        #endregion



        #region CurrentActionProgress_Max

        /// <summary>
        /// Field storage for property CurrentActionProgress_Max
        /// </summary>
        private int _CurrentActionProgress_Max = default(int);

        /// <summary>
        /// Property CurrentActionProgress_Max. TODODOC: Insert appropriate summary here
        /// </summary>
        public int CurrentActionProgress_Max
        {
            get { return _CurrentActionProgress_Max; }
            set { if (_CurrentActionProgress_Max == value) return; _CurrentActionProgress_Max = value; CurrentActionProgress_Max_RecalculateDependencies(); }
        }

        private void CurrentActionProgress_Max_RecalculateDependencies()
        {
            //Recalculate all properties here

            //NotifyOfPropertyChange is usually placed as last statement - first change all dependencies and then fire property change
            NotifyOfPropertyChange(() => CurrentActionProgress_Max);
        }

        private void CurrentActionProgress_Max_Recalculate()
        {
            _CurrentActionProgress_Max = CurrentActionProgress_Max_SMQ + CurrentActionProgress_Max_RMQ;
            //Insert your code here

            CurrentActionProgress_Max_RecalculateDependencies();
        }

        #endregion



        #region CurrentActionProgress_Value

        /// <summary>
        /// Field storage for property CurrentActionProgress_Value
        /// </summary>
        private int _CurrentActionProgress_Value = default(int);

        /// <summary>
        /// Property CurrentActionProgress_Value. TODODOC: Insert appropriate summary here
        /// </summary>
        public int CurrentActionProgress_Value
        {
            get { return _CurrentActionProgress_Value; }
            set { if (_CurrentActionProgress_Value == value) return; _CurrentActionProgress_Value = value; CurrentActionProgress_Value_RecalculateDependencies(); }
        }

        private void CurrentActionProgress_Value_RecalculateDependencies()
        {
            //Recalculate all properties here

            //NotifyOfPropertyChange is usually placed as last statement - first change all dependencies and then fire property change
            NotifyOfPropertyChange(() => CurrentActionProgress_Value);
        }

        private void CurrentActionProgress_Value_Recalculate()
        {
            _CurrentActionProgress_Value = CurrentActionProgress_Value_RMQ + CurrentActionProgress_Value_SMQ;
            //Insert your code here

            CurrentActionProgress_Value_RecalculateDependencies();
        }

        #endregion


        public event EventHandler<StatisticViewModelErrorEventArgs> StatisticViewModelError;

        private void RaiseStatisticViewModelErrorEvent(IStatisticViewModel CurrentStatisticViewModel, Exception exc)
        {
            if (StatisticViewModelError != null)
            {
                var e = new StatisticViewModelErrorEventArgs(CurrentStatisticViewModel, exc);
                StatisticViewModelError(this, e);
            }
        }

        //private void CurrentStatisticViewModel_Recalculate()
        //{
        //    _CurrentStatisticViewModel = default(StatisticViewModelBase);
        //    //Insert your code here

        //    CurrentStatisticViewModel_RecalculateDependencies();
        //}

        


        #region CurrentStatisticControl

        /// <summary>
        /// Field storage for property CurrentStatisticControl
        /// </summary>
        private Control _CurrentStatisticControl = default(Control);

        /// <summary>
        /// Property CurrentStatisticControl. TODODOC: Insert appropriate summary here
        /// </summary>
        public Control CurrentStatisticControl
        {
            get { return _CurrentStatisticControl; }
            set { if (_CurrentStatisticControl == value) return; _CurrentStatisticControl = value; CurrentStatisticControl_RecalculateDependencies(); }
        }

        private void CurrentStatisticControl_RecalculateDependencies()
        {
            //Recalculate all properties here

            //NotifyOfPropertyChange is usually placed as last statement - first change all dependencies and then fire property change
            NotifyOfPropertyChange(() => CurrentStatisticControl);
        }

        private void CurrentStatisticControl_Recalculate()
        {
            _CurrentStatisticControl = default(Control);
            //Insert your code here

            CurrentStatisticControl_RecalculateDependencies();
        }

        #endregion


        #region AvailableStatisticViewModelCollection


        //private List<IStatisticViewModel> _AvailableStatisticViewModelList; // = default(List<IStatisticViewModel>);

        /// <summary>
        /// Field storage for property AvailableStatisticViewModelCollection
        /// </summary>
        private ReadOnlyCollection<IStatisticViewModel> _AvailableStatisticViewModelCollection = default(ReadOnlyCollection<IStatisticViewModel>);

        /// <summary>
        /// Property AvailableStatisticViewModelCollection. TODODOC: Insert appropriate summary here
        /// </summary>
        public ReadOnlyCollection<IStatisticViewModel> AvailableStatisticViewModelCollection
        {
            get { return _AvailableStatisticViewModelCollection; }
            set { if (_AvailableStatisticViewModelCollection == value) return; _AvailableStatisticViewModelCollection = value; AvailableStatisticViewModelCollection_RecalculateDependencies(); }
        }

        private void AvailableStatisticViewModelCollection_RecalculateDependencies()
        {
            //Recalculate all properties here
            if (AvailableStatisticViewModelCollection == null)
            {
                CurrentStatisticViewModel = null;
            }
            else
            {
                if (CurrentStatisticViewModel == null || !AvailableStatisticViewModelCollection.Contains(CurrentStatisticViewModel))
                {
                    //CurrentStatisticViewModel = AvailableStatisticViewModelCollection.FirstOrDefault();
                }
            }
            //NotifyOfPropertyChange is usually placed as last statement - first change all dependencies and then fire property change
            NotifyOfPropertyChange(() => AvailableStatisticViewModelCollection);
        }


        #endregion

        


        protected override bool OnInitializing()
        {

            _PowersourceMainViewModel = ViewModelLocator.GetViewModel<PowersourceMainViewModel>();
            IPowersourceExt = IoC.Get<IPowersourceExt>();
            IStatisticManager = IPowersourceExt.StatisticManager;
            IReportingManager = IPowersourceExt.ReportingManager;
            
            _AvailableStatisticViewModelCollection = IReportingManager.StatisticViewModels;
            AvailableReportingContextCollection_RecalculateDependencies();
            AvailableStatisticViewModelCollection_RecalculateDependencies();

            var smq = StatisticManagerQueue;
            var rmq = RemoteBuilderQueue;

            //var allIvs = IoC.GetAllInstances(typeof(IStatisticViewModel)).Cast<IStatisticViewModel>().ToList();
            //_AvailableStatisticViewModelList = new List<IStatisticViewModel>(allIvs);
            //_AvailableStatisticViewModelCollection = new ReadOnlyCollection<IStatisticViewModel>(allIvs);

            _PowersourceMainViewModel.PropertyChanged -= _PowersourceMainViewModel_PropertyChanged;
            _PowersourceMainViewModel.PropertyChanged += _PowersourceMainViewModel_PropertyChanged;
            if (_PowersourceMainViewModel.CurrentTfsTeamProjectCollectionConfiguration != null)
            {
                _PowersourceMainViewModel.CurrentTfsTeamProjectCollectionConfiguration.PropertyChanged -= CurrentTfsTeamProjectCollectionConfiguration_PropertyChanged;
                _PowersourceMainViewModel.CurrentTfsTeamProjectCollectionConfiguration.PropertyChanged += CurrentTfsTeamProjectCollectionConfiguration_PropertyChanged;
            }


            return true;
        }

        protected override void OnDisposing()
        {
            if (_PowersourceMainViewModel != null)
            {
                _PowersourceMainViewModel.PropertyChanged -= _PowersourceMainViewModel_PropertyChanged;
                if (_PowersourceMainViewModel.CurrentTfsTeamProjectCollectionConfiguration != null)
                {
                    _PowersourceMainViewModel.CurrentTfsTeamProjectCollectionConfiguration.PropertyChanged -= CurrentTfsTeamProjectCollectionConfiguration_PropertyChanged;
                }
                _PowersourceMainViewModel = null;

            }
        }


        void CurrentTfsTeamProjectCollectionConfiguration_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            if (PropertyExtensions.IsPropertyChanged(e, () => CurrentTfsTeamProjectCollectionConfiguration.AllReportingContextCollection))
            {
                //As AvailableReportingContextCollection getter just points to CurrentTfsTeamProjectCollectionConfiguration, we simply call AvailableReportingContextCollection_RecalculateDependencies to notify dependentants and notify property has changed
                AvailableReportingContextCollection_RecalculateDependencies();
            }
        }

        void _PowersourceMainViewModel_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            if (e.PropertyName == PropertyExtensions.GetPropertyName(() => _PowersourceMainViewModel.CurrentTfsTeamProjectCollectionConfiguration))
            {
                CurrentTfsTeamProjectCollectionConfiguration_Recalculate();
            }

        }

        protected override bool OnActivating()
        {
            CurrentTfsTeamProjectCollectionConfiguration_Recalculate();
            CurrentReportingContext_RecalculateDependencies();
            CurrentStatisticViewModel_RecalculateDependencies();
            CurrentStatisticControl_RecalculateDependencies();
            IsCalculating_RecalculateDependencies();
            if (CurrentStatisticViewModel != null)
            {
                CurrentStatisticViewModel.Activate();

            }
            return true;
        }
        protected override bool OnDeactivating()
        {
            if (CurrentStatisticViewModel != null)
            {
                CurrentStatisticViewModel.Deactivate();
            }
            return true;
        }

        public void BackToMain()
        {
            IViewModel main = ViewModelLocator.GetViewModel<PowersourceMainViewModel>();
            if (!main.IsInitialized) main.Initialize();
            IUIManager ui = IoC.Get<IUIManager>();
            ui.ActivateViewModelInConductor(main, ui.GetConductorForViewModel(this));
        }

        public bool RequestCreateNewReportingContext(string name)
        {
            if (AvailableReportingContextCollection == null) return false;
            var res = AvailableReportingContextCollection.FirstOrDefault(a => a.Label == name);

            if (res != null)
            {
                return false;
            }
            else
            {
                var newCon = new ReportingContext(CurrentTfsTeamProjectCollectionConfiguration, null) { Label = name, Name = name };
                newCon.Initialize();
                CurrentTfsTeamProjectCollectionConfiguration.AllReportingContextCollection.Add(newCon);
                CurrentReportingContext = newCon;
                return true;
            }
        }

        private string _NameExistsCaption = "Name exists!";
        public string NameExistsCaption { get { return _NameExistsCaption; } }

        private string _NameExistsMsg = "There is already a reporting context with this name! Please choose a different one.";
        public string NameExistsMsg { get { return _NameExistsMsg; } }

        public void RequestDeleteCurrentReportingContext()
        {
            if (AvailableReportingContextCollection.Count == 1)
            {
                if (FireCannotDeleteError != null) FireCannotDeleteError(this, EventArgs.Empty);
            }
            else
                if (FireDeleteConfirmationDialog != null) FireDeleteConfirmationDialog(this, EventArgs.Empty);
        }

        public void DeleteCurrentReportingContext()
        {
            var toBeDeleted = CurrentReportingContext;

            foreach (var context in AvailableReportingContextCollection)
            {
                if (context != toBeDeleted)
                {
                    CurrentReportingContext = context;
                    break;
                }
            }

            CurrentTfsTeamProjectCollectionConfiguration.AllReportingContextCollection.Remove(toBeDeleted);
        }

        public void RequestForceRecalculate()
        {
            if (FireRecalculateDialog != null) FireRecalculateDialog(this, EventArgs.Empty);
        }

        public void ForceRecalculate()
        {
            if (CurrentReportingContext == null) return;
            
            SynchronizeStatisticViewModelAndStatistics(true);
            

        }



        public event EventHandler FireRecalculateDialog;

        private string _RecalculateMsg = "Are you sure you want to force recalculation for the current context?";
        public string RecalculateMsg { get { return _RecalculateMsg; } }

        private string _RecalculateCaption = "Confirm Recalculation";
        public string RecalculateCaption { get { return _RecalculateCaption; } }

        public event EventHandler FireCannotDeleteError;

        private string _CannotDeleteMsg = "Cannot delete the last reporting context!";
        public string CannotDeleteMsg { get { return _CannotDeleteMsg; } }

        private string _CannotDeleteCaption = "Cannot delete!";
        public string CannotDeleteCaption { get { return _CannotDeleteCaption; } }

        public event EventHandler FireDeleteConfirmationDialog;

        private string _DeleteConfirmationMsg = "Are you sure you want to delete the current reporting context?";
        public string DeleteConfirmationMsg { get { return _DeleteConfirmationMsg; } }

        private string _DeleteConfirmationCaption = "Confirm deletion!";
        public string DeleteConfirmationCaption { get { return _DeleteConfirmationCaption; } }

        #region DeferedAction

        //class DeferredChangeNotification
        //{
        //    public IStatisticViewModel StatisticViewModel { get; private set; }
        //    public DeferredChangeNotifications DeferredChangeNotificationType { get; private set; }
        //    public ReportingContext ReportingContext { get; private set; }
        //    public object Sender { get; private set; }
        //    public NotifyCollectionChangedEventArgs CollectionChangedEventArgs { get; private set; }
        //    public DeferredChangeNotification(IStatisticViewModel svm, DeferredChangeNotifications dcn, ReportingContext rc, object sender, NotifyCollectionChangedEventArgs e)
        //    {
        //        StatisticViewModel = svm;
        //        DeferredChangeNotificationType = dcn;
        //        ReportingContext = rc;
        //        CollectionChangedEventArgs = e;
        //        Sender = sender;
        //    }


        //}



        //List<DeferredChangeNotification> DeferredNotifications = new List<DeferredChangeNotification>();

        public enum DeferredChangeNotifications
        {
            ActiveTfsTeamProjectConfigurationChanged,
            ActiveTimeFrameChanged,
            ActiveStatisticChanged,
            ShowNormalizedChanged,
            TeamProjectConfigurationsCollectionChanged,
            TimeFramesCollectionChanged,
            StatisticsCollectionChanged,
            OnReportingContextChanged,
            //Activate,
            //Deactivate,
            //LoadAndActivate
        }

        private void EnsureActionAfterCalculation(IStatisticViewModel svm, DeferredChangeNotifications dcn, object sender, NotifyCollectionChangedEventArgs e)
        {
            CheckAndFireIfNotCalculating(svm, dcn, null, sender, e);
        }

        void CheckAndFireIfNotCalculating(IStatisticViewModel svm, DeferredChangeNotifications dcn, ReportingContext rc = null, object sender = null, NotifyCollectionChangedEventArgs e = null)
        {
            if (!IsCalculating)
            {
                PlayDeferedNotification(svm, dcn, rc, sender, e);
            }
            else
            {
                //We simply ignore the event as the whole view will be recalculated once recalculation is done
                return;

                //if (DeferredNotifications == null) DeferredNotifications = new List<DeferredChangeNotification>();
                //var enqueuedItem = DeferredNotifications.FirstOrDefault(a => a.StatisticViewModel == svm && a.DeferredChangeNotification == dcn);
                //if (enqueuedItem != null)
                //{
                //    // if the deferred action already in the list we remove it and after if we put it at the end
                //    DeferredNotifications.Remove(enqueuedItem);
                //}
                //else
                //{
                //    enqueuedItem = new DeferredChangeNotification(svm, dcn, rc, sender, e);
                //}
                ////putting DeferredNotifications at the end of the list
                //DeferredNotifications.Add(enqueuedItem);
            }
        }


        private void PlayDeferedNotification(IStatisticViewModel svm, DeferredChangeNotifications dcn, ReportingContext rc, object sender, NotifyCollectionChangedEventArgs e)
        {
            switch (dcn)
            {
                case DeferredChangeNotifications.ActiveTfsTeamProjectConfigurationChanged:
                    svm.ActiveTfsTeamProjectConfigurationChanged();
                    break;
                case DeferredChangeNotifications.ActiveTimeFrameChanged:
                    svm.ActiveTimeFrameChanged();
                    break;
                case DeferredChangeNotifications.ActiveStatisticChanged:
                    svm.ActiveStatisticChanged();
                    break;
                case DeferredChangeNotifications.ShowNormalizedChanged:
                    svm.ShowNormalizedChanged();
                    break;
                case DeferredChangeNotifications.TeamProjectConfigurationsCollectionChanged:
                    svm.TeamProjectConfigurationsCollectionChanged(sender, e);
                    break;
                case DeferredChangeNotifications.TimeFramesCollectionChanged:
                    svm.TimeFramesCollectionChanged(sender, e);
                    break;
                case DeferredChangeNotifications.StatisticsCollectionChanged:
                    svm.StatisticsCollectionChanged(sender, e);
                    break;
                case DeferredChangeNotifications.OnReportingContextChanged:
                    svm.OnReportingContextChanged(rc);
                    break;
                //case DeferredChangeNotifications.Activate:
                //    var control = UIManager.GetOrCreateControl(svm);
                //    svm.OnReportingContextChanged(rc);
                //    CurrentStatisticControl = control;
                //    break;
                //case DeferredChangeNotifications.Deactivate:
                //    svm.Deactivate();
                //    break;
                //case DeferredChangeNotifications.LoadAndActivate:
                   
                    //break;
                default:
                    break;
            }
        }

        //private void PlayDeferedActionForDeferredChangeNotification(DeferredChangeNotification dcnItem)
        //{
        //    if (CurrentStatisticViewModel == null)
        //        Log.Error(null, "CurrentStatisticViewModel == null, cannot play deferred action");
        //    if (CurrentStatisticViewModel != dcnItem.StatisticViewModel)
        //    {
        //        var svmTitle = "#NULL";
        //        if (CurrentStatisticViewModel != null) svmTitle = CurrentStatisticViewModel.Title;
        //        Log.Warn("Ignoring replay of {0}. CurrentStatisticViewModel ={1}", dcnItem.ToString(), svmTitle);
        //    }
        //    var svm = dcnItem.StatisticViewModel;
        //    var rc = dcnItem.ReportingContext;
        //    var dcn = dcnItem.DeferredChangeNotificationType;
        //    object sender = dcnItem.Sender;
        //    var e = dcnItem.CollectionChangedEventArgs;

        //    PlayDeferedNotification(svm, dcn, rc, sender, e);
        //}

        //bool IsActivationDeferred()
        //{
        //    if (CurrentStatisticViewModel == null) return false;
        //    var dn = DeferredNotifications.FirstOrDefault(
        //        a => a.StatisticViewModel == CurrentStatisticViewModel && 
        //            (
        //            a.DeferredChangeNotificationType == DeferredChangeNotifications.LoadAndActivate 
        //            || 
        //            a.DeferredChangeNotificationType == DeferredChangeNotifications.Activate
        //            ));
        //    return (dn!=null) ;
        //}

        //void PlayAllDeferedNotifications()
        //{
        //    if (DeferredNotifications == null || DeferredNotifications.Count() == 0) return;
        //    var lastActivated = DeferredNotifications.LastOrDefault(a => a.DeferredChangeNotificationType == DeferredChangeNotifications.Activate);
        //    var lastDeactivated = DeferredNotifications.LastOrDefault(a => a.DeferredChangeNotificationType == DeferredChangeNotifications.Deactivate);
        //    if (lastDeactivated != null)
        //    {
        //        lastDeactivated.StatisticViewModel.Deactivate();
        //    }
        //    if (lastActivated != null)
        //    {
        //        if (lastActivated.StatisticViewModel != CurrentStatisticViewModel)
        //        {
        //            Log.Error(null, "PlayDefered actions ignored value for activated: lastActivated.StatisticViewModel = {0},CurrentStatisticViewModel={1}", lastActivated.StatisticViewModel, CurrentStatisticViewModel);
        //        }
        //    }
        //    if (CurrentStatisticViewModel == null)
        //    {
        //        DeferredNotifications.Clear();
        //        return;
        //    }
        //    else
        //    {
        //        var allActionForSCVM = DeferredNotifications.Where(a => a.StatisticViewModel == CurrentStatisticViewModel).ToList();
        //        DeferredNotifications.Clear();
        //        var activatedItemToReplay = allActionForSCVM.Where(a => a.DeferredChangeNotificationType == DeferredChangeNotifications.LoadAndActivate);
        //        if (activatedItemToReplay.Count() > 0)
        //        {
        //            PlayDeferedActionForDeferredChangeNotification(activatedItemToReplay.First());
        //        }
        //        else
        //        {
        //            activatedItemToReplay = allActionForSCVM.Where(a => a.DeferredChangeNotificationType == DeferredChangeNotifications.Activate);
        //            if (activatedItemToReplay.Count() > 0)
        //            {
        //                PlayDeferedActionForDeferredChangeNotification(activatedItemToReplay.First());
        //            }
        //            else
        //            {
        //                return;

        //                //We ignore all the events as the full recalculation will be fired
        //                //foreach (var dcnItem in allActionForSCVM)
        //                //{
        //                //    PlayDeferedActionForDeferredChangeNotification(dcnItem);
        //                //}
        //            }

        //        }

        //    }
        //    DeferredNotifications.Clear();

        //}

        #endregion

    }
}
